import java.io.IOException;
import java.util.Iterator;
import java.util.Vector;
import org.htmlparser.Attribute;
import org.htmlparser.Node;
import org.htmlparser.Parser;
import org.htmlparser.Tag;
import org.htmlparser.filters.TagNameFilter;
import org.htmlparser.nodes.TagNode;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.NodeTreeWalker;
import org.htmlparser.util.ParserException;

public class ScriptExtractor {

	private Parser parser;
	private NodeList tempList = new NodeList();
	private Vector<ScriptNode> scriptList = new Vector<ScriptNode>();
	AttrTable attr = AttrTable.getInstance();
	EventTable events = EventTable.getInstance();
	TagsTable tags = TagsTable.getInstance();
	boolean addFlag = false;

	public ScriptExtractor(Parser parser) throws ParserException{
		this.parser = parser;
		parser.reset();
	}

	public ScriptExtractor(String url) throws ParserException{
		this.parser = new Parser(url);
		parser.reset();
	}

	public Vector<ScriptNode> getScriptNodes() throws ParserException, DetectorException, IOException {

		ScriptNode sn = null;
		boolean doNormalize = true;
		
		try{
			tempList = parser.extractAllNodesThatMatch(new TagNameFilter("html"));
		}catch (org.htmlparser.util.EncodingChangeException e)
		{
			parser.reset();
			tempList = parser.extractAllNodesThatMatch(new TagNameFilter("html"));
		}
		if (tempList.size()<1)
			return scriptList;
		//traverse whole tree (depth first) and find script nodes
		NodeTreeWalker walker = new NodeTreeWalker(tempList.elementAt(0),true);
		while (walker.hasMoreNodes()){
			Node current = walker.nextNode();
			// if it isn't a Tag Node it is not interesting
			if (current instanceof TagNode) {
				//downcast to Tag Class to handle attributes easily
				Tag tag = (Tag)current;
				// set addFlag to flase indicating this node isn't in list yet
				addFlag = false;
				//get all attributes
				Vector<Attribute> nodeAttributes = tag.getAttributesEx();
				for (Iterator<Attribute> iter = nodeAttributes.iterator();iter.hasNext();){
					Attribute currentAttr = iter.next();
					String currentAttrValue = currentAttr.getValue();
					String currentAttrName = currentAttr.getName();
					if (currentAttrName !=null) {

						//check for suspicious tag names ("Script")
						for (int i=0;i<tags.getTable().size();i++){
							String type = tags.getTable().elementAt(i);
							if (currentAttrName.toLowerCase().equals(type)){
								sn = new ScriptNode(current,type);
								if (sn.build(scriptList))
									scriptList.add(sn);
								addFlag = true;
								break;
							}		
						}
						if (addFlag == true)
							break;

						//check for suspicious attributes ("src", "background" ...) that may point to an external script
						for (int i=0;i<attr.getTable().size();i++){
							String type = attr.getTable().elementAt(i);
							if ( (currentAttrValue != null) && (currentAttrName.toLowerCase() .equals(type)) ) {
								sn = new ScriptNode(current,type);
								if (sn.build(scriptList))
									scriptList.add(sn);
								addFlag = true;
								break;
							}		
						}
						if (addFlag == true)
							break;

						//check for suspicious events ("onload", "onmouseover" ...) that doesn't have "javascript:" inside
						for (int i=0;i<events.getTable().size();i++){
							String type = events.getTable().elementAt(i);
							if ((currentAttrValue != null) && (currentAttrName.toLowerCase().equals(type))) {
								sn = new ScriptNode(current,type);
								if (sn.build(scriptList))
									scriptList.add(sn);
								addFlag = true;
								break;
							}		
						}
					}
				}
			}
		}
		return scriptList;
	}
}

